<!DOCTYPE html>
<html lang='zh-CN'>

<head>
  <meta name="generator" content="Hexo 6.3.0">
  <meta name="hexo-theme" content="https://github.com/xaoxuu/hexo-theme-stellar/tree/1.19.0">
  <meta charset="utf-8">
  

  <meta http-equiv='x-dns-prefetch-control' content='on' />
  <link rel='dns-prefetch' href='https://gcore.jsdelivr.net'>
  <link rel="preconnect" href="https://gcore.jsdelivr.net" crossorigin>
  <link rel='dns-prefetch' href='//unpkg.com'>

  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="theme-color" content="#f8f8f8">
  
  <title>微信&支付宝付款实现 - 愔颂</title>

  
    <meta name="description" content="微信&amp;支付宝付款实现，包括API接入指引和相关方法实现。">
<meta property="og:type" content="article">
<meta property="og:title" content="微信&amp;支付宝付款实现">
<meta property="og:url" content="https://farhills.gitee.io/2023/10/05/%E5%BE%AE%E4%BF%A1&%E6%94%AF%E4%BB%98%E5%AE%9D%E4%BB%98%E6%AC%BE%E5%AE%9E%E7%8E%B0/index.html">
<meta property="og:site_name" content="愔颂">
<meta property="og:description" content="微信&amp;支付宝付款实现，包括API接入指引和相关方法实现。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1694862276536-1e3bd461-38bb-4cca-954c-c194a8662f5f.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1694866690777-39df90ed-22cc-41f2-aaf9-12b2f49d2931.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1694867523626-74dcec4a-1ab7-4893-aba4-b41e611a051c.png">
<meta property="og:image" content="https://pay.weixin.qq.com/wiki/doc/apiv3/assets/img/common/ico-guide/chapter1_5_1.png">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1696496947507-f9d18fd7-d05a-4776-a2d9-a42e64fc167b.png">
<meta property="og:image" content="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/assets/img/common/pay/chapter3_1_2.png">
<meta property="article:published_time" content="2023-10-05T10:54:25.438Z">
<meta property="article:modified_time" content="2023-10-05T10:54:25.703Z">
<meta property="article:author" content="远岫">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://cdn.nlark.com/yuque/0/2023/png/36098302/1694862276536-1e3bd461-38bb-4cca-954c-c194a8662f5f.png">
  
  
  
  

  <!-- feed -->
  

  
    
<link rel="stylesheet" href="/css/main.css">

  

  
    <link rel="shortcut icon" href="https://z1.ax1x.com/2023/10/05/pPXijyT.png">
  

  

  


  
</head>

<body>
  




  <div class='l_body' id='start'>
    <aside class='l_left' layout='post'>
    

  

<header class="header"><div class="logo-wrap"><a class="avatar" href="/about/"><div class="bg" style="opacity:0;background-image:url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.4/avatar/round/rainbow64@3x.webp);"></div><img no-lazy class="avatar" src="https://s1.ax1x.com/2022/11/12/ziJjfK.jpg" onerror="javascript:this.classList.add('error');this.src='https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.4/image/2659360.svg';"></a><a class="title" href="/"><div class="main" ff="title">愔颂</div></a></div>

<nav class="menu dis-select"><a class="nav-item active" href="/">文章</a><a class="nav-item" href="/friends/">收藏</a><a class="nav-item" href="/about/">关于</a></nav>
</header>


<div class="widgets">
<widget class="widget-wrapper search"><div class="widget-body"><div class="search-wrapper" id="search"><form class="search-form"><input type="text" class="search-input" id="search-input" data-filter="/blog/" placeholder="文章搜索"><svg t="1670596976048" class="icon search-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2676" width="200" height="200"><path d="M938.2 832.6L723.8 618.1c-2.5-2.5-5.3-4.4-7.9-6.4 36.2-55.6 57.3-121.8 57.3-193.1C773.3 222.8 614.6 64 418.7 64S64 222.8 64 418.6c0 195.9 158.8 354.6 354.6 354.6 71.3 0 137.5-21.2 193.2-57.4 2 2.7 3.9 5.4 6.3 7.8L832.5 938c14.6 14.6 33.7 21.9 52.8 21.9 19.1 0 38.2-7.3 52.8-21.8 29.2-29.1 29.2-76.4 0.1-105.5M418.7 661.3C284.9 661.3 176 552.4 176 418.6 176 284.9 284.9 176 418.7 176c133.8 0 242.6 108.9 242.6 242.7 0 133.7-108.9 242.6-242.6 242.6" p-id="2677"></path></svg></form><div id="search-result"></div><div class="search-no-result">没有找到内容！</div></div></div></widget>


<widget class="widget-wrapper toc single" id="data-toc"><div class="widget-header cap dis-select"><span class="name">微信&支付宝付款实现</span></div><div class="widget-body fs14"><div class="doc-tree active"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%80%E3%80%81%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E4%BB%8B%E7%BB%8D%E5%92%8C%E6%8E%A5%E5%85%A5%E6%8C%87%E5%BC%95"><span class="toc-text">一、微信支付介绍和接入指引</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D"><span class="toc-text">1、微信支付产品介绍</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E6%8E%A5%E5%85%A5%E6%8C%87%E5%BC%95"><span class="toc-text">2、接入指引</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E6%94%AF%E4%BB%98%E5%AE%89%E5%85%A8%EF%BC%88%E8%AF%81%E4%B9%A6-%E7%A7%98%E9%92%A5-%E7%AD%BE%E5%90%8D%EF%BC%89"><span class="toc-text">二、支付安全（证书&#x2F;秘钥&#x2F;签名）</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E7%9A%84%E5%9F%BA%E7%A1%80-%E6%9C%BA%E5%AF%86%E6%80%A7"><span class="toc-text">1、信息安全的基础 - 机密性</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E5%92%8C%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86"><span class="toc-text">2、对称加密和非对称加密</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81"><span class="toc-text">3、身份认证</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4%E3%80%81%E6%91%98%E8%A6%81%E7%AE%97%E6%B3%95%EF%BC%88Digest-Algorithm%EF%BC%89"><span class="toc-text">4、摘要算法（Digest Algorithm）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5%E3%80%81%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D"><span class="toc-text">5、数字签名</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6%E3%80%81%E6%95%B0%E5%AD%97%E8%AF%81%E4%B9%A6"><span class="toc-text">6、数字证书</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7%E3%80%81%E5%BE%AE%E4%BF%A1APIv3%E8%AF%81%E4%B9%A6"><span class="toc-text">7、微信APIv3证书</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8%E3%80%81API%E5%AF%86%E9%92%A5%E5%92%8CAPIv3%E5%AF%86%E9%92%A5"><span class="toc-text">8、API密钥和APIv3密钥</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%89%E3%80%81%E5%9F%BA%E7%A1%80%E6%94%AF%E4%BB%98API-V3"><span class="toc-text">三、基础支付API V3</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81%E5%BC%95%E5%85%A5%E6%94%AF%E4%BB%98%E5%8F%82%E6%95%B0"><span class="toc-text">1、引入支付参数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E5%8A%A0%E8%BD%BD%E5%95%86%E6%88%B7%E7%A7%81%E9%92%A5"><span class="toc-text">2、加载商户私钥</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81%E8%8E%B7%E5%8F%96%E7%AD%BE%E5%90%8D%E9%AA%8C%E8%AF%81%E5%99%A8%E5%92%8CHttpClient"><span class="toc-text">3、获取签名验证器和HttpClient</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4%E3%80%81API%E5%AD%97%E5%85%B8%E5%92%8C%E7%9B%B8%E5%85%B3%E5%B7%A5%E5%85%B7"><span class="toc-text">4、API字典和相关工具</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5%E3%80%81Native%E4%B8%8B%E5%8D%95API"><span class="toc-text">5、Native下单API</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#5-1%E3%80%81Native%E6%94%AF%E4%BB%98%E6%B5%81%E7%A8%8B"><span class="toc-text">5.1、Native支付流程</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-2%E3%80%81%E7%AD%BE%E5%90%8D%E5%92%8C%E9%AA%8C%E7%AD%BE%E5%8E%9F%E7%90%86"><span class="toc-text">5.2、签名和验签原理</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6%E3%80%81%E6%94%AF%E4%BB%98%E9%80%9A%E7%9F%A5API"><span class="toc-text">6、支付通知API</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#6-1%E3%80%81%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F"><span class="toc-text">6.1、内网穿透</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-2%E3%80%81%E5%95%86%E6%88%B7%E5%AE%9A%E6%97%B6%E6%9F%A5%E8%AF%A2%E6%9C%AC%E5%9C%B0%E8%AE%A2%E5%8D%95"><span class="toc-text">6.2、商户定时查询本地订单</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7%E3%80%81%E7%94%A8%E6%88%B7%E5%8F%96%E6%B6%88%E8%AE%A2%E5%8D%95API"><span class="toc-text">7、用户取消订单API</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8%E3%80%81%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E6%9F%A5%E5%8D%95API"><span class="toc-text">8、微信支付查单API</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9%E3%80%81%E7%94%B3%E8%AF%B7%E9%80%80%E6%AC%BEAPI"><span class="toc-text">9、申请退款API</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10%E3%80%81%E6%9B%B4%E5%A4%9A"><span class="toc-text">10、更多</span></a></li></ol></li></ol></div></div></widget>




</div>


    </aside>
    <div class='l_main'>
      

      



<div class="bread-nav fs12"><div id="breadcrumb"><a class="cap breadcrumb" href="/">主页</a><span class="sep"></span><a class="cap breadcrumb" href="/">文章</a><span class="sep"></span><a class="cap breadcrumb-link" href="/categories/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/">项目实战</a></div><div id="post-meta">发布于&nbsp;<time datetime="2023-10-05T10:54:25.438Z">2023-10-05</time></div></div>

<article class='md-text content post'>
<h1 class="article-title"><span>微信&支付宝付款实现</span></h1>
<meta name="referrer" content="no-referrer"/>

<p>微信&amp;支付宝付款实现，包括API接入指引和相关方法实现。</p>
<span id="more"></span>

<hr>
<h1 id="一、微信支付介绍和接入指引"><a href="#一、微信支付介绍和接入指引" class="headerlink" title="一、微信支付介绍和接入指引"></a>一、微信支付介绍和接入指引</h1><hr>
<h2 id="1、微信支付产品介绍"><a href="#1、微信支付产品介绍" class="headerlink" title="1、微信支付产品介绍"></a>1、微信支付产品介绍</h2><hr>
<p><a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/static/product/product_intro.shtml?name=qrcode">微信支付产品介绍</a></p>
<p><strong>1.1、付款码支付</strong> </p>
<p>用户展示微信钱包内的“付款码”给商家，商家扫描后直接完成支付，适用于线下面对面收银的场景。 </p>
<p><strong>1.2、JSAPI支付</strong> </p>
<p>线下场所：商户展示一个支付二维码，用户使用微信扫描二维码后，输入需要支付的金额，完成支付。 </p>
<p>公众号场景：用户在微信内进入商家公众号，打开某个页面，选择某个产品，完成支付。 </p>
<p>PC网站场景：在网站中展示二维码，用户使用微信扫描二维码，输入需要支付的金额，完成支付。 </p>
<p>特点：用户在客户端输入支付金额 </p>
<p><strong>1.3、小程序支付</strong> </p>
<p>在微信小程序平台内实现支付的功能。 </p>
<p><strong>1.4、Native支付</strong> </p>
<p>Native支付是指商户展示支付二维码，用户再用微信“扫一扫”完成支付的模式。这种方式适用于PC网 站。 特点：商家预先指定支付金额 </p>
<p><strong>1.5、APP支付</strong> </p>
<p>商户通过在移动端独立的APP应用程序中集成微信支付模块，完成支付。 </p>
<p><strong>1.6、刷脸支付</strong> </p>
<p>用户在刷脸设备前通过摄像头刷脸、识别身份后进行的一种支付方式。  </p>
<h2 id="2、接入指引"><a href="#2、接入指引" class="headerlink" title="2、接入指引"></a>2、接入指引</h2><p><strong>2.1、获取商户号</strong> </p>
<p>微信商户平台：<a href="about:blank">https://pay.weixin.qq.com/ </a></p>
<p>场景：Native支付 </p>
<p>步骤：提交资料 &#x3D;&gt; 签署协议 &#x3D;&gt; 获取商户号 </p>
<p><strong>2.2、获取APPID</strong> </p>
<p>微信公众平台：<a href="about:blank">https://mp.weixin.qq.com/</a> </p>
<p>步骤：注册服务号 &#x3D;&gt; 服务号认证 &#x3D;&gt; 获取APPID &#x3D;&gt; 绑定商户号 </p>
<p><strong>2.3、获取API秘钥</strong> </p>
<p>APIv2版本的接口需要此秘钥 </p>
<p>步骤：登录商户平台 &#x3D;&gt; 选择 账户中心 &#x3D;&gt; 安全中心 &#x3D;&gt; API安全 &#x3D;&gt; 设置API密钥 </p>
<p><strong>2.4、获取APIv3秘钥</strong> </p>
<p>APIv3版本的接口需要此秘钥 步骤：登录商户平台 &#x3D;&gt; 选择 账户中心 &#x3D;&gt; 安全中心 &#x3D;&gt; API安全 &#x3D;&gt; 设置APIv3</p>
<p>密钥 随机密码生成工具：<a href="about:blank">https://suijimimashengcheng.bmcx.com/ </a></p>
<p><strong>2.5、申请商户API证书</strong> </p>
<p>APIv3版本的所有接口都需要；</p>
<p>APIv2版本的高级接口需要（如：退款、企业红包、企业付款等） </p>
<p>步骤：登录商户平台 &#x3D;&gt; 选择 账户中心 &#x3D;&gt; 安全中心 &#x3D;&gt; API安全 &#x3D;&gt; 申请API证书 </p>
<p><strong>2.6、获取微信平台证书</strong> </p>
<p>可以预先下载，也可以通过编程的方式获取。后面的课程中，我们会通过编程的方式来获取。 </p>
<p>注意：以上所有API秘钥和证书需妥善保管防止泄露  </p>
<h1 id="二、支付安全（证书-秘钥-签名）"><a href="#二、支付安全（证书-秘钥-签名）" class="headerlink" title="二、支付安全（证书&#x2F;秘钥&#x2F;签名）"></a>二、支付安全（证书&#x2F;秘钥&#x2F;签名）</h1><hr>
<h2 id="1、信息安全的基础-机密性"><a href="#1、信息安全的基础-机密性" class="headerlink" title="1、信息安全的基础 - 机密性"></a>1、信息安全的基础 - 机密性</h2><hr>
<ul>
<li><p><strong>明文</strong>：加密前的消息叫“明文”（plain text） </p>
</li>
<li><p><strong>密文</strong>：加密后的文本叫“密文”（cipher text） </p>
</li>
<li><p><strong>密钥</strong>：只有掌握特殊“钥匙”的人，才能对加密的文本进行解密，这里的“钥匙”就叫做“密钥”（key） </p>
<blockquote>
<p>“密钥”就是一个字符串，度量单位是“位”（bit），比如，密钥长度是 128，就是 16 字节的二进制串 </p>
</blockquote>
</li>
<li><p><strong>加密</strong>：实现机密性最常用的手段是“加密”（encrypt）</p>
<blockquote>
<p>按照密钥的使用方式，加密可以分为两大类：对称加密和非对称加密。 </p>
</blockquote>
</li>
<li><p><strong>解密</strong>：使用密钥还原明文的过程叫“解密”（decrypt） </p>
</li>
<li><p><strong>加密算法</strong>：加密解密的操作过程就是“加密算法” </p>
<blockquote>
<p>所有的加密算法都是公开的，而算法使用的“密钥”则必须保密</p>
</blockquote>
</li>
</ul>
<h2 id="2、对称加密和非对称加密"><a href="#2、对称加密和非对称加密" class="headerlink" title="2、对称加密和非对称加密"></a>2、对称加密和非对称加密</h2><hr>
<p><strong>对称加密</strong> </p>
<ul>
<li>特点：只使用一个密钥，密钥必须保密，常用的有 AES算法 </li>
<li>优点：运算速度快 </li>
<li>缺点：秘钥需要信息交换的双方共享，一旦被窃取，消息会被破解，无法做到安全的密钥交换</li>
</ul>
<p><strong>非对称加密</strong> </p>
<ul>
<li>特点：使用两个密钥：公钥和私钥，公钥可以任意分发而私钥保密，常用的有 RSA </li>
<li>优点：黑客获取公钥无法破解密文，解决了密钥交换的问题 </li>
<li>缺点：运算速度非常慢，混合加密，实际场景中把对称加密和非对称加密结合起来使用。</li>
</ul>
<h2 id="3、身份认证"><a href="#3、身份认证" class="headerlink" title="3、身份认证"></a>3、身份认证</h2><hr>
<ul>
<li>公钥加密，私钥解密的作用是加密信息 </li>
<li>私钥加密，公钥解密的作用是身份认证</li>
</ul>
<blockquote>
<p>示例：bob给susan写了一封信，为了加密，bob用它的公钥进行加密，susan拥有bob的私钥，因此可以进行解密。而如果bob用私钥进行加密，bob的其他好友都有公钥，并且能够解密，说明这封信是bob写的，相当于身份认证。</p>
</blockquote>
<h2 id="4、摘要算法（Digest-Algorithm）"><a href="#4、摘要算法（Digest-Algorithm）" class="headerlink" title="4、摘要算法（Digest Algorithm）"></a>4、摘要算法（Digest Algorithm）</h2><p>摘要算法就是我们常说的散列函数、哈希函数（Hash Function），它能够把任意长度的数据“压缩”成 固定长度、而且独一无二的“摘要”字符串，就好像是给这段数据生成了一个数字“指纹”。 </p>
<p><strong>作用：</strong></p>
<ul>
<li>保证信息的完整性和唯一性 ，确保信息没有被篡改。</li>
</ul>
<p><strong>特性：</strong> </p>
<ul>
<li>不可逆：只有算法，没有秘钥，只能加密，不能解密 </li>
<li>难题友好性：想要破解，只能暴力枚举 </li>
<li>发散性：只要对原文进行一点点改动，摘要就会发生剧烈变化 </li>
<li>抗碰撞性：原文不同，计算后的摘要也要不同 常见摘要算法： MD5、SHA1、SHA2（SHA224、SHA256、SHA384）</li>
</ul>
<h2 id="5、数字签名"><a href="#5、数字签名" class="headerlink" title="5、数字签名"></a>5、数字签名</h2><p>数字签名是使用私钥对摘要加密生成签名，需要由公钥将签名解密后进行验证，实现身份认证和不可否认签名和验证签名的流程：  </p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1694862276536-1e3bd461-38bb-4cca-954c-c194a8662f5f.png" fancybox="true"/></div></div>

<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/403704980">https://zhuanlan.zhihu.com/p/403704980</a></p>
<h2 id="6、数字证书"><a href="#6、数字证书" class="headerlink" title="6、数字证书"></a>6、数字证书</h2><p>数字证书解决“公钥的信任”问题，可以防止黑客伪造公钥。 不能直接分发公钥，公钥的分发必须使用数字证书，数字证书由CA颁发 。</p>
<p>https协议中的数字证书：  </p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1694866690777-39df90ed-22cc-41f2-aaf9-12b2f49d2931.png" fancybox="true"/></div></div>



<h2 id="7、微信APIv3证书"><a href="#7、微信APIv3证书" class="headerlink" title="7、微信APIv3证书"></a>7、微信APIv3证书</h2><p>商户证书： 商户API证书是指由商户申请的，包含商户的商户号、公司名称、公钥信息的证书。 </p>
<p>商户证书在商户后台申请：<a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/index.php/core/cert/api_cert#/">https://pay.weixin.qq.com/index.php/core/cert/api_cert#/</a>  </p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1694867523626-74dcec4a-1ab7-4893-aba4-b41e611a051c.png" fancybox="true"/></div></div>



<h2 id="8、API密钥和APIv3密钥"><a href="#8、API密钥和APIv3密钥" class="headerlink" title="8、API密钥和APIv3密钥"></a>8、API密钥和APIv3密钥</h2><p>都是对称加密需要使用的加密和解密密钥，一定要保管好，不能泄露。 </p>
<p>API密钥对应V2版本的API APIv3密钥对应V3版本的API  </p>
<h1 id="三、基础支付API-V3"><a href="#三、基础支付API-V3" class="headerlink" title="三、基础支付API V3"></a>三、基础支付API V3</h1><h2 id="1、引入支付参数"><a href="#1、引入支付参数" class="headerlink" title="1、引入支付参数"></a>1、引入支付参数</h2><p><strong>1、定义微信支付相关参数</strong>  </p>
<p>将资料文件夹中的 wxpay.properties 复制到resources目录中这个文件定义了之前我们准备的微信支付相关的参数，例如商户号、APPID、API秘钥等 。</p>
<p><strong>2、读取支付参数</strong>  </p>
<p>将资料文件夹中的 config 目录中的 WxPayConfig.java 复制到源码目录中  </p>
<h2 id="2、加载商户私钥"><a href="#2、加载商户私钥" class="headerlink" title="2、加载商户私钥"></a>2、加载商户私钥</h2><p><strong>1、复制商户私钥</strong></p>
<p> 将下载的私钥文件复制到项目根目录下：  </p>
<p><strong>2、引入SDK</strong></p>
<p> <a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay6_0.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay6_0.shtml</a> </p>
<p>我们可以使用官方提供的 SDK，帮助我们完成开发。实现了请求签名的生成和应答签名的验证。</p>
<p><strong>3、获取商户私钥</strong> </p>
<p><a target="_blank" rel="noopener" href="https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient">https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient</a> （如何加载商户私钥）  </p>
<h2 id="3、获取签名验证器和HttpClient"><a href="#3、获取签名验证器和HttpClient" class="headerlink" title="3、获取签名验证器和HttpClient"></a>3、获取签名验证器和HttpClient</h2><p> <strong>1、证书密钥使用说明</strong></p>
<p> <a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay3_0.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay3_0.shtml</a>  </p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://pay.weixin.qq.com/wiki/doc/apiv3/assets/img/common/ico-guide/chapter1_5_1.png" fancybox="true"/></div></div>

<p><strong>2、获取签名验证器</strong> </p>
<p><a target="_blank" rel="noopener" href="https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient">https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient</a> （定时更新平台证书功能） </p>
<p>平台证书：平台证书封装了微信的公钥，商户可以使用平台证书中的公钥进行验签。</p>
<p>签名验证器：帮助我们进行验签工作，我们单独将它定义出来，方便后面的开发。</p>
<p><strong>3、 获取 HttpClient 对象</strong> </p>
<p><a target="_blank" rel="noopener" href="https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient">https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient</a> （定时更新平台证书功能） </p>
<p>HttpClient 对象：是建立远程连接的基础，我们通过SDK创建这个对象。 </p>
<h2 id="4、API字典和相关工具"><a href="#4、API字典和相关工具" class="headerlink" title="4、API字典和相关工具"></a>4、API字典和相关工具</h2><p><strong>1、API列表</strong> </p>
<p><a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_3.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_3.shtml</a> </p>
<p>我们的项目中要实现以下所有API的功能。  </p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://cdn.nlark.com/yuque/0/2023/png/36098302/1696496947507-f9d18fd7-d05a-4776-a2d9-a42e64fc167b.png" fancybox="true"/></div></div>

<p> <strong>2、接口规则</strong> </p>
<p><a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay2_0.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay2_0.shtml</a> </p>
<p>微信支付 APIv3 使用 JSON 作为消息体的数据交换格式。  </p>
<h2 id="5、Native下单API"><a href="#5、Native下单API" class="headerlink" title="5、Native下单API"></a>5、Native下单API</h2><h3 id="5-1、Native支付流程"><a href="#5-1、Native支付流程" class="headerlink" title="5.1、Native支付流程"></a>5.1、Native支付流程</h3><p><a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_4.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_4.shtml</a>  </p>
<div class="tag-plugin image"><div class="image-bg"><img src="https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/assets/img/common/pay/chapter3_1_2.png" fancybox="true"/></div></div>

<h3 id="5-2、签名和验签原理"><a href="#5-2、签名和验签原理" class="headerlink" title="5.2、签名和验签原理"></a>5.2、签名和验签原理</h3><p>签名生成流程：<br><a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml</a>  </p>
<p>签名验证流程：<br><a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml</a>  </p>
<h2 id="6、支付通知API"><a href="#6、支付通知API" class="headerlink" title="6、支付通知API"></a>6、支付通知API</h2><h3 id="6-1、内网穿透"><a href="#6-1、内网穿透" class="headerlink" title="6.1、内网穿透"></a>6.1、内网穿透</h3><p>ngrok是一款用于实现内网穿透的工具。它可以帮助你将本地部署的服务器暴露给公网，使外部网络可以访问到你的本地服务。</p>
<p>支付通知API：<a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml</a>  </p>
<p>流程：</p>
<ol>
<li>启用ngrok内网穿透</li>
<li>设置通知地址</li>
<li>创建通知接口</li>
<li>通知验签</li>
<li>通知数据解密</li>
<li>处理订单</li>
<li>处理重复通知，在处理订单时加数据锁。</li>
</ol>
<h3 id="6-2、商户定时查询本地订单"><a href="#6-2、商户定时查询本地订单" class="headerlink" title="6.2、商户定时查询本地订单"></a>6.2、商户定时查询本地订单</h3><p>支付成功后，商户侧查询本地数据库，订单是否支付成功 。</p>
<p><strong>1、后端定义商户查单接口</strong>  </p>
<p><strong>2、前端定时轮询查单</strong>  </p>
<p>在二维码展示页面，前端定时轮询查询订单是否已支付，如果支付成功则跳转到订单页面 。</p>
<h2 id="7、用户取消订单API"><a href="#7、用户取消订单API" class="headerlink" title="7、用户取消订单API"></a>7、用户取消订单API</h2><p>流程：</p>
<ol>
<li>添加取消订单接口</li>
<li>调用微信支付的关单接口（创建远程请求对象、组装json请求体、完成签名并执行请求）</li>
<li>处理订单状态</li>
</ol>
<h2 id="8、微信支付查单API"><a href="#8、微信支付查单API" class="headerlink" title="8、微信支付查单API"></a>8、微信支付查单API</h2><p>商户后台未收到异步支付结果通知时，商户应该主动调用《微信支付查单接口》，同步订单状态 。</p>
<p>流程：</p>
<ol>
<li>集成Spring Task启动定时任务查找超时未支付的订单</li>
<li>调用微信查单接口获取订单状态，如已支付，更新订单状态，若未支付，调用关单接口。</li>
</ol>
<h2 id="9、申请退款API"><a href="#9、申请退款API" class="headerlink" title="9、申请退款API"></a>9、申请退款API</h2><p>文档：<a target="_blank" rel="noopener" href="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_9.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_9.shtml</a>  </p>
<p>流程：</p>
<ol>
<li>创建退款单</li>
<li>调用退款API</li>
<li>更新订单、退款单</li>
</ol>
<h2 id="10、更多"><a href="#10、更多" class="headerlink" title="10、更多"></a>10、更多</h2><p>同下单流程，同样有查询退款API、退款结果通知API、申请和下载账单API。</p>





</article>

<div class="related-wrap reveal" id="read-next"><section class="body"><div class="item" id="prev"><div class="note">较新文章</div><a href="/2023/10/05/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E6%91%98%E5%BD%95/">设计模式摘录</a></div><div class="item" id="next"><div class="note">较早文章</div><a href="/2023/10/05/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0AOP%E5%88%87%E9%9D%A2/">自定义注解实现AOP切面</a></div></section></div>






  <div class='related-wrap md-text reveal' id="comments">
    <section class='header cmt-title cap theme'>
      快来参与讨论吧
    </section>
    <section class='body cmt-body giscus'>
      

<svg class="loading" style="vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2709"><path d="M832 512c0-176-144-320-320-320V128c211.2 0 384 172.8 384 384h-64zM192 512c0 176 144 320 320 320v64C300.8 896 128 723.2 128 512h64z" p-id="2710"></path></svg>

<div id="giscus" data-repo="echoalways/giscus" data-repo-id="R_kgDOKjJRiQ" data-category="Announcements" data-category-id="DIC_kwDOKjJRic4CaUxu" data-mapping="pathname" data-strict="0" data-reactions-enabled="1" data-emit-metadata="0" data-input-position="top" data-theme="preferred_color_scheme" data-lang="zh-CN" data-loading="lazy" crossorigin="anonymous"></div>

    </section>
  </div>



      
<footer class="page-footer reveal fs12"><hr><div class="text" style="text-align:center;"><p>云无心以出岫@远岫♥</p>
<div><span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>，<span id="busuanzi_container_site_pv">总访问量: <span id="busuanzi_value_site_pv"></span>次</span>，<span id="busuanzi_container_site_uv">访客数: <span id="busuanzi_value_site_uv"></span>人</span></div></div></footer>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<script>
  function createtime() {
    var now = new Date();
    var grt= new Date("10/03/2023 18:40:00");
    now.setTime(now.getTime()+250);
    days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days);
    hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours);
    if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
    mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;}
    seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
    snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;}
    document.getElementById("timeDate").innerHTML = "本站已运行 "+dnum+" 天 ";
    document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
  };
  setInterval("createtime()",250);
</script>

      <div class='float-panel mobile-only blur' style='display:none'>
  <button type='button' class='sidebar-toggle mobile' onclick='sidebar.toggle()'>
    <svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15301"><path d="M566.407 808.3c26.9-0.1 49.3-20.8 51.6-47.6-1.9-27.7-23.9-49.7-51.6-51.6h-412.6c-28.2-1.4-52.6 19.5-55.5 47.6 2.3 26.8 24.6 47.5 51.6 47.6h416.5v4z m309.3-249.9c26.9-0.1 49.3-20.8 51.6-47.6-2.2-26.8-24.6-47.5-51.6-47.6h-721.9c-27.7-2.8-52.5 17.4-55.3 45.1-0.1 0.8-0.1 1.7-0.2 2.5 0.9 27.2 23.6 48.5 50.7 47.6H875.707z m-103.1-245.9c26.9-0.1 49.3-20.8 51.6-47.6-0.4-28.3-23.2-51.1-51.5-51.6h-618.9c-29.5-1.1-54.3 21.9-55.5 51.4v0.2c1.4 27.8 25.2 49.2 53 47.8 0.8 0 1.7-0.1 2.5-0.2h618.8z" p-id="15302"></path><path d="M566.407 808.3c26.9-0.1 49.3-20.8 51.6-47.6-1.9-27.7-23.9-49.7-51.6-51.6h-412.6c-28.2-1.4-52.6 19.5-55.5 47.6 1.9 27.7 23.9 49.7 51.6 51.6h416.5z m309.3-249.9c26.9-0.1 49.3-20.8 51.6-47.6-2.2-26.8-24.6-47.5-51.6-47.6h-721.9c-27.7-2.8-52.5 17.4-55.3 45.1-0.1 0.8-0.1 1.7-0.2 2.5 0.9 27.2 23.6 48.5 50.7 47.6H875.707z m-103.1-245.9c26.9-0.1 49.3-20.8 51.6-47.6-0.4-28.3-23.2-51.1-51.5-51.6h-618.9c-29.5-1.1-54.3 21.9-55.5 51.4v0.2c1.4 27.8 25.2 49.2 53 47.8 0.8 0 1.7-0.1 2.5-0.2h618.8z" p-id="15303"></path></svg>
  </button>
</div>

    </div>
  </div>
  <div class='scripts'>
    <script type="text/javascript">
  const stellar = {
    // 懒加载 css https://github.com/filamentgroup/loadCSS
    loadCSS: (href, before, media, attributes) => {
      var doc = window.document;
      var ss = doc.createElement("link");
      var ref;
      if (before) {
        ref = before;
      } else {
        var refs = (doc.body || doc.getElementsByTagName("head")[0]).childNodes;
        ref = refs[refs.length - 1];
      }
      var sheets = doc.styleSheets;
      if (attributes) {
        for (var attributeName in attributes) {
          if (attributes.hasOwnProperty(attributeName)) {
            ss.setAttribute(attributeName, attributes[attributeName]);
          }
        }
      }
      ss.rel = "stylesheet";
      ss.href = href;
      ss.media = "only x";
      function ready(cb) {
        if (doc.body) {
          return cb();
        }
        setTimeout(function () {
          ready(cb);
        });
      }
      ready(function () {
        ref.parentNode.insertBefore(ss, before ? ref : ref.nextSibling);
      });
      var onloadcssdefined = function (cb) {
        var resolvedHref = ss.href;
        var i = sheets.length;
        while (i--) {
          if (sheets[i].href === resolvedHref) {
            return cb();
          }
        }
        setTimeout(function () {
          onloadcssdefined(cb);
        });
      };
      function loadCB() {
        if (ss.addEventListener) {
          ss.removeEventListener("load", loadCB);
        }
        ss.media = media || "all";
      }
      if (ss.addEventListener) {
        ss.addEventListener("load", loadCB);
      }
      ss.onloadcssdefined = onloadcssdefined;
      onloadcssdefined(loadCB);
      return ss;
    },

    // 从 butterfly 和 volantis 获得灵感
    loadScript: (src, opt) => new Promise((resolve, reject) => {
      var script = document.createElement('script');
      if (src.startsWith('/')){
        src = stellar.config.root + src.substring(1);
      }
      script.src = src;
      if (opt) {
        for (let key of Object.keys(opt)) {
          script[key] = opt[key]
        }
      } else {
        // 默认异步，如果需要同步，第二个参数传入 {} 即可
        script.async = true
      }
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    }),

    // https://github.com/jerryc127/hexo-theme-butterfly
    jQuery: (fn) => {
      if (typeof jQuery === 'undefined') {
        stellar.loadScript(stellar.plugins.jQuery).then(fn)
      } else {
        fn()
      }
    }
  };
  stellar.version = '1.19.0';
  stellar.github = 'https://github.com/xaoxuu/hexo-theme-stellar/tree/1.19.0';
  stellar.config = {
    date_suffix: {
      just: '刚刚',
      min: '分钟前',
      hour: '小时前',
      day: '天前',
      month: '个月前',
    },
    root : '/',
  };

  // required plugins (only load if needs)
  stellar.plugins = {
    jQuery: 'https://gcore.jsdelivr.net/npm/jquery@3.6.2/dist/jquery.min.js'
  };

  if ('local_search') {
    stellar.search = {};
    stellar.search.service = 'local_search';
    if (stellar.search.service == 'local_search') {
      let service_obj = Object.assign({}, {"field":"all","path":"/search.json","content":true,"sort":"-date"});
      stellar.search[stellar.search.service] = service_obj;
    }
  }

  // stellar js
  stellar.plugins.stellar = Object.assign({"sites":"/js/plugins/sites.js","friends":"/js/plugins/friends.js","ghinfo":"/js/plugins/ghinfo.js","timeline":"/js/plugins/timeline.js","linkcard":"/js/plugins/linkcard.js","fcircle":"/js/plugins/fcircle.js","weibo":"/js/plugins/weibo.js"});

  stellar.plugins.marked = Object.assign("https://cdn.bootcdn.net/ajax/libs/marked/4.0.18/marked.min.js");
  // optional plugins
  if ('false' == 'true') {
    stellar.plugins.lazyload = Object.assign({"enable":false,"js":"https://gcore.jsdelivr.net/npm/vanilla-lazyload@17.8.3/dist/lazyload.min.js","transition":"blur"});
  }
  if ('true' == 'true') {
    stellar.plugins.swiper = Object.assign({"enable":true,"css":"https://unpkg.com/swiper@8.4.5/swiper-bundle.min.css","js":"https://unpkg.com/swiper@8.4.5/swiper-bundle.min.js"});
  }
  if ('' == 'true') {
    stellar.plugins.scrollreveal = Object.assign({"enable":null,"js":"https://gcore.jsdelivr.net/npm/scrollreveal@4.0.9/dist/scrollreveal.min.js","distance":"8px","duration":500,"interval":100,"scale":1});
  }
  if ('true' == 'true') {
    stellar.plugins.preload = Object.assign({"enable":true,"service":"flying_pages","instant_page":"https://gcore.jsdelivr.net/gh/volantis-x/cdn-volantis@4.1.2/js/instant_page.js","flying_pages":"https://gcore.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"});
  }
  if ('true' == 'true') {
    stellar.plugins.fancybox = Object.assign({"enable":true,"js":"https://gcore.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js","css":"https://gcore.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css","selector":".swiper-slide img"});
  }
  if ('false' == 'true') {
    stellar.plugins.heti = Object.assign({"enable":false,"css":"https://unpkg.com/heti@0.9.2/umd/heti.min.css","js":"https://unpkg.com/heti@0.9.2/umd/heti-addon.min.js"});
  }
  if ('true' == 'true') {
    stellar.plugins.copycode = Object.assign({"enable":true,"js":"/js/plugins/copycode.js","default_text":"Copy","success_text":"Copied"});
  }
</script>

<!-- required -->

  
<script src="/js/main.js" async></script>



<!-- optional -->

  <script>
  function loadJS() {
    const els = document.querySelectorAll("#comments #giscus");
    if (els.length === 0) return;
    els.forEach((el, i) => {
      try {
        el.innerHTML = '';
      } catch (error) {
        console.log(error);
      }
      var script = document.createElement('script');
      script.src = 'https://giscus.app/client.js';
      script.async = true;
      for (let key of Object.keys(el.attributes)) {
        let attr = el.attributes[key];
        if (['class', 'id'].includes(attr.name) === false) {
          script.setAttribute(attr.name, attr.value);
        }
      }
      el.appendChild(script);
    });
  }
  window.addEventListener('DOMContentLoaded', (event) => {
    loadJS();
  });
</script>




<!-- inject -->


  </div>
</body>
</html>
